package com.godme.structure;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

public class BinaryTreeNode {
    private final Integer value;
    private BinaryTreeNode leftNode;
    private BinaryTreeNode rightNode;


    public BinaryTreeNode(Integer value){
        this.value = value;
    }

    public BinaryTreeNode(Integer value, Integer leftValue, Integer rightValue){
        this.value = value;
        addLeftValue(leftValue);
        addRightValue(rightValue);
    }

    public void addLeftNode(BinaryTreeNode node){
        this.leftNode = node;
    }

    public void addRightNode(BinaryTreeNode node){
        this.rightNode = node;
    }

    public void addLeftValue(Integer value){
        addLeftNode(new BinaryTreeNode(value));
    }

    public void addRightValue(Integer value){
        addRightNode(new BinaryTreeNode(value));
    }

    public static void main(String[] args) {
        BinaryTreeNode leftNode = new BinaryTreeNode(2, 1,3);
        BinaryTreeNode rightNode = new BinaryTreeNode(6, 5, 7);
        BinaryTreeNode rootNode = new BinaryTreeNode(4);
        rootNode.addLeftNode(leftNode);
        rootNode.addRightNode(rightNode);

        rootNode.forwardShow();

        System.err.println("=================");

        rootNode.middleShow();
        System.err.println("================");

        rootNode.backwardShow();
        System.err.println("================");


        rootNode.levelShow();
    }






    private void showValue(){
        System.err.println(value);
    }

    public void forwardShow(){
        showValue();
        if(leftNode != null){
            leftNode.forwardShow();
        }
        if(rightNode != null){
            rightNode.forwardShow();
        }
    }

    public void backwardShow(){
        if(leftNode != null){
            leftNode.backwardShow();
        }
        if(rightNode != null){
            rightNode.backwardShow();
        }
        showValue();
    }

    public void middleShow(){
        if(leftNode != null){
            leftNode.middleShow();
        }
        showValue();
        if(rightNode != null){
            rightNode.middleShow();
        }
    }

    public void levelShow(){
        doLevelShow(Collections.singletonList(this));
    }

    private void doLevelShow(List<BinaryTreeNode> nodes){
        if(nodes.isEmpty()){
            return;
        }
        LinkedList<BinaryTreeNode> nextLevelNodes = new LinkedList<BinaryTreeNode>();
        for (BinaryTreeNode node : nodes){
            node.showValue();
            if(node.leftNode != null){
                nextLevelNodes.add(node.leftNode);
            }
            if(node.rightNode != null){
                nextLevelNodes.add(node.rightNode);
            }
        }
        doLevelShow(nextLevelNodes);
    }

    public void levelShow2(){
        LinkedBlockingQueue<BinaryTreeNode> nodes = new LinkedBlockingQueue<BinaryTreeNode>(){
            {
                add(BinaryTreeNode.this);
            }
        };

        BinaryTreeNode cursor = null;
        while(!nodes.isEmpty()){
          cursor = nodes.peek();
          cursor.showValue();
          if(cursor.leftNode != null){
              nodes.add(cursor.leftNode);
          }
          if(cursor.rightNode != null){
              nodes.add(rightNode);
          }
        }
    }



}
